package pikes.ecma;

import java.util.Iterator;
import java.util.LinkedList;

public class FunctionExpression extends PrintableExpression implements IMemberExpression {

	private CharSequence identifier = null;

	private SourceElements sourceElements = new SourceElements();

	private LinkedList<CharSequence> formalParameterList = new LinkedList<CharSequence>();

	public FunctionExpression() {

	}

	public FunctionExpression(CharSequence identifier) {
		super();
		this.identifier = identifier;
	}

	public void add(SourceElement sourceElement) {
		if (sourceElement != null) {
			sourceElements.add(sourceElement);
		}
	}

	public void add(IExpression expression) {
		add(new ExpressionStatement(expression));
	}

	public void addFormalParameter(CharSequence formalParameter) {
		if (formalParameterList != null) {
			formalParameterList.add(formalParameter);
		}
	}

	public void visit(SyntaxTreeVisitor syntaxVisitor) {
		syntaxVisitor.Function();

		if (identifier != null) {
			syntaxVisitor.whiteSpace();
			syntaxVisitor.identifier(identifier);
		}

		syntaxVisitor.beforeParameterList();
		Iterator<CharSequence> formalParameterListIterator = formalParameterList.iterator();
		while (formalParameterListIterator.hasNext()) {
			syntaxVisitor.identifier(formalParameterListIterator.next());
			if (formalParameterListIterator.hasNext()) {
				syntaxVisitor.comma();
			}
		}
		syntaxVisitor.afterParameterList();

		syntaxVisitor.openCurlyBrace();
		sourceElements.visit(syntaxVisitor);
		syntaxVisitor.closeCurlyBrace();
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof FunctionExpression)) {
			return false;
		}

		FunctionExpression thatFunctionExpression = (FunctionExpression) obj;

		if (!(identifier.equals(thatFunctionExpression.identifier))) {
			return false;
		}

		if (!(formalParameterList.equals(thatFunctionExpression.formalParameterList))) {
			return false;
		}

		if (!(sourceElements.equals(thatFunctionExpression.sourceElements))) {
			return false;
		}

		return true;
	}

	@Override
	public int hashCode() {

		int hash = 0;

		hash = hash + identifier.hashCode();

		for (CharSequence parameter : formalParameterList) {
			hash = hash + parameter.hashCode();
		}

		hash = hash + sourceElements.hashCode();

		return hash;
	}
}
